import { NextRequest, NextResponse } from "next/server";

/**
 * 设置为Edge运行时，避免源站传输；依靠CDN/浏览器缓存来优化性能
 */
export const runtime = "edge";

/**
 * 上游API基础URL，从环境变量获取或使用默认值
 */
const UPSTREAM = process.env.NOF1_API_BASE_URL || "https://nof1.ai/api";

/**
 * 根据路径第一段设置不同的缓存时间(TTL)映射表
 * 用于平衡数据新鲜度与传输成本
 * 注意：对于时间对齐轮询，s-maxage应与客户端对齐间隔匹配，以最大化缓存命中率
 * 大多数客户端对齐到10秒边界
 */
const TTL_BY_SEGMENT: Record<string, number> = {
  // 高度易变数据 - 浏览器缓存较短，但CDN缓存设为10秒以对齐轮询
  "crypto-prices": 5,
  // 实时但非逐笔数据 - 对齐到10秒客户端轮询
  "account-totals": 10,
  positions: 10,
  conversations: 30,
  leaderboard: 60,
  // 与其他实时端点一起对齐到10秒
  trades: 10,
  "since-inception-values": 600,
  analytics: 300,
};

/**
 * 根据路径部分生成适当的缓存控制头
 * @param pathParts 路径片段数组
 * @returns 缓存控制头字符串
 */
function cacheHeaderFor(pathParts: string[]): string {
  // 获取路径的第一个段（API端点类型）
  const seg = pathParts[0] || "";
  // 获取对应的TTL，默认为30秒
  const ttl = TTL_BY_SEGMENT[seg] ?? 30;

  // 为时间对齐端点（10秒客户端轮询）设置s-maxage以匹配对齐
  // 这确保第一个请求命中源站，后续请求命中Edge缓存
  let sMax: number;
  if (
    seg === "crypto-prices" ||
    seg === "account-totals" ||
    seg === "positions" ||
    seg === "trades"
  ) {
    // 将CDN缓存对齐到10秒边界，以匹配客户端时间对齐
    sMax = 10;
  } else {
    // 非实时端点使用较长的CDN缓存时间
    sMax = Math.max(ttl * 2, 30);
  }

  // 设置stale-while-revalidate值，允许使用过期缓存同时在后台刷新
  const swr = Math.max(ttl * 4, 60);
  // 包含max-age以便浏览器重复轮询时命中本地缓存
  return `public, max-age=${ttl}, s-maxage=${sMax}, stale-while-revalidate=${swr}`;
}

/**
 * 处理GET请求，代理到上游API
 * @param req Next.js请求对象
 * @param ctx 上下文，包含路径参数
 * @returns 代理响应
 */
export async function GET(
  req: NextRequest,
  ctx: { params: Promise<{ path: string[] }> },
) {
  // 获取路径参数
  const { path } = await ctx.params;
  // 过滤掉空路径片段
  const parts = (path || []).filter(Boolean);
  // 构建子路径
  const subpath = parts.join("/");
  // 构建完整的目标URL
  const target = `${UPSTREAM}/${subpath}${req.nextUrl.search}`;

  console.log("获取交易数据的路由：", target);
  // 转发条件头，以便上游可以返回304状态码（未修改），最小化返回的数据量
  const passHeaders: Record<string, string> = { Accept: "application/json" };
  const ifNoneMatch = req.headers.get("if-none-match");
  const ifModifiedSince = req.headers.get("if-modified-since");
  if (ifNoneMatch) passHeaders["if-none-match"] = ifNoneMatch;
  if (ifModifiedSince) passHeaders["if-modified-since"] = ifModifiedSince;

  // 调用上游API
  const upstream = await fetch(target, {
    // 在Edge fetch层不缓存，依靠下面设置的响应头进行缓存
    cache: "no-store",
    headers: passHeaders,
  });

  // 流式传输上游响应体，避免在内存中缓冲大型有效载荷
  const res = new NextResponse(upstream.body, {
    status: upstream.status,
    headers: {
      "content-type":
        upstream.headers.get("content-type") ||
        "application/json; charset=utf-8",
      "cache-control": cacheHeaderFor(parts),
      "cdn-cache-control": cacheHeaderFor(parts),
      // 对跨域本地开发有帮助；此处对公共数据是安全的
      "access-control-allow-origin": "*",
      // 当存在ETag/Last-Modified时传播它们，以启用浏览器重新验证
      ...(upstream.headers.get("etag")
        ? { etag: upstream.headers.get("etag")! }
        : {}),
      ...(upstream.headers.get("last-modified")
        ? { "last-modified": upstream.headers.get("last-modified")! }
        : {}),
      Vary: "Accept-Encoding",
    },
  });
  console.log("打印api/nof1/[...path]/route.ts的请求target：", target);
  // console.log("打印api/nof1/[...path]/route.ts的请求结果：", res.body);
  return res;
}

/**
 * 处理OPTIONS请求，用于CORS预检
 * @returns 包含CORS头的响应
 */
export async function OPTIONS() {
  return new NextResponse(null, {
    headers: {
      "access-control-allow-origin": "*",
      "access-control-allow-methods": "GET,OPTIONS",
      "access-control-allow-headers": "*",
      "cache-control": "public, max-age=3600, s-maxage=3600",
    },
  });
}
